# -*- coding: utf-8 -*-

from chinese_calendar import is_holiday
from datetime import date
from datetime import datetime
from datetime import timedelta

#上班时间
officeHours = "09:00:00"
#下班时间
closingTime = "18:00:00"
#午休开始时间
lunchBreakStart = "12:00:00"
#午休结束时间
lunchBreakEnd = "14:00:00"



def get_holiday(year):
    list_holiday=[]
    year=int(year)
    for month in range(1,13):
        for day in range(1,32):
            try:
                dt=date(year,month,day)
            except:
                break
            if is_holiday(dt):
                list_holiday.append('{}-{:02d}-{:02d}'.format(year,month,day))
    return list_holiday

def datediff_no_holiday(start,end):
    """Params:
    start:开始时间
    end:结束时间
    'yyyy-mm-dd hh24:mi:ss'格式字符串"""
    if start>=end or not start or not end:return 0
    if start[:4]==end[:4]:
        list_holiday=get_holiday(end[:4])
    else:
        list_holiday=[]
        for year in range(int(start[:4]),int(end[:4])+1):
            list_holiday=list_holiday+get_holiday(str(year))
    list_holiday=list( map(lambda x : datetime.strptime(x,'%Y-%m-%d'), list_holiday) )
    result=0
    list_start=start.split(' ')
    start=datetime.strptime(start, '%Y-%m-%d %H:%M:%S')
    start_d=datetime.strptime(list_start[0],'%Y-%m-%d')
    list_end=end.split(' ')
    end=datetime.strptime(end, '%Y-%m-%d %H:%M:%S')
    end_d=datetime.strptime(list_end[0],'%Y-%m-%d')
    #首先判断结束时间是否在工作时间内，如果早于当天工作时间则转换为上班时间，如果大于则转换为后一天上班时间
    if list_end[1]>closingTime:
        end=end_d+timedelta(hours=18)
    if list_end[1]<officeHours:
        end=end_d+timedelta(hours=9)
        list_end[1]=officeHours
    #同理判断开始时间，如果大于则转换为后一天上班时间
    if list_start[1]>closingTime:
        start_d+=timedelta(days=1)
        start=start_d+timedelta(hours=9)
        list_start[1]=officeHours
    #判断是否在节假日（包括不补班的周末）中，如果是则转入下一天进行循环判断
    if start_d in list_holiday:
        while start_d in list_holiday:
            start_d+=timedelta(days=1)
        start=start_d+timedelta(hours=9)
        list_start[1]=officeHours
    if end_d in list_holiday:
        while end_d in list_holiday:
            end_d+=timedelta(days=1)
        end=end_d+timedelta(hours=9)
        list_end[1]=officeHours
    #判断开始时间，如果早于当天工作时间则转换为当天上班时间
    if list_start[1]<officeHours:
        start=start_d+timedelta(hours=9)
    #剔除12点到14点的午休时间
    if lunchBreakStart<list_start[1]<lunchBreakEnd:
        start=start_d+timedelta(hours=14)
        list_start[1]=lunchBreakEnd
    if start>=end:return 0
    #如果开始与结束在同一日期里
    if start_d==end_d:
        result=(end-start).seconds
        if list_start[1]<=lunchBreakStart:  #如果开始时间在上午
            if list_end[1]>=lunchBreakEnd:
                result-=7200
            if lunchBreakStart<list_end[1]<lunchBreakEnd:
                result-=(end-(end_d+timedelta(hours=12))).seconds
    #如果开始与结束不在同一日期里，排除中间可能存在的节假日
    else:
        if list_start[1]<=lunchBreakStart:
            result-=7200
        result+=(start_d+timedelta(hours=18)-start).seconds
        start_d+=timedelta(days=1) #
        while start_d<end_d:
            if start_d not in list_holiday:
                result+=27000  #每日工时7.5*3600秒
            start_d+=timedelta(days=1)
        result+=(end-(end_d+timedelta(hours=9))).seconds
        if list_end[1]>=lunchBreakEnd:
            result-=7200
        elif lunchBreakStart<list_end[1]<lunchBreakEnd:
            result-=(end-(end_d+timedelta(hours=12))).seconds

    return result if result>0 else 0
    """返回相差的秒数"""

if __name__ == '__main__':
    start='2022-03-05 9:00:00'
    end='2022-03-07 17:00:00'
    hours=datediff_no_holiday(start,end)
    print(hours/60,'分钟')
